use crate::{c::C, user::User};
use std::{collections::HashMap, sync::Arc, time::Duration};
use tokio::{
    io::AsyncReadExt,
    net::{tcp::OwnedReadHalf, TcpListener, TcpStream},
    sync::{
        mpsc::{channel, Sender},
        Mutex,
    },
    time::sleep,
}; // 引入异步 IO、网络和多线程相关的库 // 引入自定义的 C 和 User 类

/// CIM 服务器
pub struct Server {
    ip_addr: String,                                           // 服务器 IP 地址
    port: u16,                                                 // 服务器端口号
    c: C<String>,                                              // 用于消息广播的通道
    online_map: Arc<Mutex<HashMap<String, Arc<Mutex<User>>>>>, // 在线用户列表，使用 Arc 和 Mutex 实现多线程安全
}

impl Server {
    /// 创建一个新的 CIM 服务器实例
    pub fn new(ip_addr: String, port: u16) -> Self {
        Self {
            ip_addr,
            port,
            c: C::new(3000),                                  // 初始化消息广播通道
            online_map: Arc::new(Mutex::new(HashMap::new())), // 初始化在线用户列表
        }
    }

    /// 启动 CIM 服务器
    pub async fn start(&self) {
        let addr = (self.ip_addr.as_str(), self.port);
        let listener = TcpListener::bind(addr).await.unwrap(); // 监听指定地址和端口号的 TCP 连接
        self.listen_msg().await; // 启动消息监听线程
        while let Ok((conn, _)) = listener.accept().await {
            // 接受新的 TCP 连接
            self.handle(conn).await; // 处理新的连接
        }
    }

    /// 处理一个 TCP 连接
    pub async fn handle(&self, conn: TcpStream) {
        let socket_addr = conn.peer_addr().unwrap(); // 获取连接的远程地址
                                                     //sleep(Duration::from_secs(10)).await;
                                                     //conn.shutdown().await.unwrap();
        let (read, write) = conn.into_split(); // 将连接的读写端口分离

        let r_arc = Arc::new(Mutex::new(read)); // 将读端口包装成 Arc 和 Mutex，以便多线程共享
        let w_arc = Arc::new(Mutex::new(write)); // 将写端口包装成 Arc 和 Mutex，以便多线程共享
        let user = User::new(socket_addr, r_arc.clone(), w_arc.clone()).await; // 创建一个新的用户实例
        let arc_user = Arc::new(Mutex::new(user)); // 将用户实例包装成 Arc 和 Mutex，以便多线程共享
        User::on_line(arc_user.clone(), self.c.tx.clone(), self.online_map.clone()).await; // 将用户加入在线列表
        self.do_msg(r_arc.clone(), arc_user).await; // 处理用户发送的消息
    }

    /// 处理用户发送的消息
    pub async fn do_msg(&self, reade: Arc<Mutex<OwnedReadHalf>>, user: Arc<Mutex<User>>) {
        let tx = self.c.tx.clone(); // 获取消息广播通道的发送端口
        let mut buffer = [0; 1024]; // 创建一个 1024 字节大小的缓冲区
        let online_map = self.online_map.clone(); // 获取在线用户列表的 Arc 和 Mutex，以便多线程共享

        tokio::spawn(async move {
            loop {
                let mut conn = reade.lock().await; // 获取读端口的 Mutex 锁
                if let Ok(x) = conn.read(&mut buffer).await {
                    // 从读端口读取数据
                    let tx = tx.clone(); // 获取消息广播通道的发送端口的克隆
                    if x == 0 {
                        // 如果读取到的数据长度为 0，说明连接已经关闭
                        User::off_line(user.clone(), tx, online_map.clone()).await; // 将用户从在线列表中移除
                        return;
                    } else {
                        let msg = String::from_utf8(buffer[..x - 1].to_vec()).unwrap(); // 将读取到的数据转换成字符串
                        if msg.starts_with("/") {
                            // 如果消息以 / 开头，说明是用户发送的命令
                            user.lock().await.do_msg(online_map.clone(), msg).await;
                            // 处理用户发送的命令
                        } else {
                            // 否则，说明是用户发送的聊天消息
                            Self::broad_cast(user.clone(), tx, &msg).await; // 广播聊天消息给所有在线用户
                        }
                    }
                }
            }
        });
    }

    /// 启动消息监听线程
    pub async fn listen_msg(&self) {
        let rx = self.c.rx.clone(); // 获取消息广播通道的接收端口
        let clone_map = self.online_map.clone(); // 获取在线用户列表的 Arc 和 Mutex，以便多线程共享

        tokio::spawn(async move {
            let mut rx = rx.lock().await; // 获取消息广播通道的接收端口的 Mutex 锁
            while let Some(msg) = rx.recv().await {
                // 从消息广播通道接收消息
                let clone_map = clone_map.clone(); // 获取在线用户列表的 Arc 和 Mutex 的克隆，以便多线程共享
                tokio::spawn(async move {
                    let guard_map = clone_map.lock().await; // 获取在线用户列表的 Mutex 锁
                    dbg!(msg.clone()); // 打印接收到的消息
                    for (_, user) in guard_map.iter() {
                        // 遍历在线用户列表
                        let tx = user.lock().await.c.tx.clone(); // 获取用户的消息发送端口
                        tx.send(msg.clone()).await.unwrap(); // 发送消息给用户
                        println!("user: {:?},msg:{msg}", user.lock().await.name)
                        // 打印发送的消息
                    }
                });
            }
        });
    }

    /// 广播聊天消息给所有在线用户
    pub async fn broad_cast(user: Arc<Mutex<User>>, tx: Sender<String>, msg: &str) {
        let msg = msg.to_string(); // 将消息转换成字符串
        tokio::spawn(async move {
            let user = user.lock().await; // 获取用户的 Mutex 锁
            let msg = format!("[{}:{}] {}:{}", user.ip, user.port, user.name, msg); // 格式化聊天消息
            let tx = tx.clone(); // 获取消息广播通道的发送端口的克隆
            tx.send(msg).await.unwrap(); // 发送消息给所有在线用户
        });
    }
}
///TODO:  https://skyao.io/learning-tokio/docs/tutorial/select.html
async fn timeout() {
    let (tx, mut rx) = channel::<bool>(1);
    tokio::spawn(async move {
        let mut temp = 0;
        loop {
            tx.send(true).await.unwrap();
            sleep(Duration::from_secs(temp)).await;
            temp += 1
        }
    });
}
